package org.dromara.system.controller.monitor;

import cn.dev33.satoken.annotation.SaCheckPermission;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.system.domain.vo.CacheListInfoVo;
import org.redisson.spring.data.connection.RedissonConnectionFactory;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;


/**
 * @Author 刘武贵
 * @Date 2024/8/15 22:00
 * @Description 功能描述：缓存监控
 */
@RequiredArgsConstructor
@RestController
@RequestMapping("/monitor/cache")
public class CacheController {

    /**
     * Redisson连接工厂，用于管理和创建与Redis服务器的连接
     * 作为私有最终字段，确保了在对象创建后不能再被修改，保证了连接工厂的唯一性和稳定性
     */
    private final RedissonConnectionFactory connectionFactory;

    /**
     * 获取缓存监控列表
     */
    @SaCheckPermission("monitor:cache:list")
    @GetMapping()
    public R<CacheListInfoVo> getInfo() throws Exception {
        // 通过连接工厂获取Redis连接
        RedisConnection connection = connectionFactory.getConnection();
        // 获取命令使用统计信息
        Properties commandStats = connection.commands().info("commandstats");

        // 初始化命令统计列表
        List<Map<String, String>> pieList = new ArrayList<>();
        if (commandStats != null) {
            // 遍历命令统计属性，准备命令使用数据
            commandStats.stringPropertyNames().forEach(key -> {
                Map<String, String> data = new HashMap<>(2);
                // 获取属性值
                String property = commandStats.getProperty(key);
                // 移除属性名称前的"cmdstat_"前缀，并存储到Map中
                data.put("name", StringUtils.removeStart(key, "cmdstat_"));
                // 提取属性值中调用次数和微秒数之间的部分，并存储到Map中
                data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
                pieList.add(data);
            });
        }

        // 准备缓存监控信息视图对象
        CacheListInfoVo infoVo = new CacheListInfoVo();
        // 设置基本信息，包括连接的命令信息
        infoVo.setInfo(connection.commands().info());
        // 设置数据库大小，即当前数据库中的键的数量
        infoVo.setDbSize(connection.commands().dbSize());
        // 设置命令统计信息，此处的pieList是一个包含命令统计的数据列表
        infoVo.setCommandStats(pieList);
        // 返回成功的响应，包含缓存信息视图对象
        return R.ok(infoVo);
    }

}
